/*
 * H26xNaluParser.cpp
 *
 *  Created on: 2018年9月18日
 *      Author: zhengboyuan
 */

#include "H26xNaluParser.h"

namespace av
{

H26xNaluParser::H26xNaluParser()
{
}

H26xNaluParser::~H26xNaluParser()
{
}


const uint8_t H26xNaluParser::s_startCode[START_CODE_LENGTH] = { 0, 0, 0, 1};


const uint8_t* H26xNaluParser::getStartCode()
{
    return s_startCode;

}


bool H26xNaluParser::hasStartCode(const uint8_t* data, size_t length)
{
    if (length < 4)
    {
        return false;
    }

    if (data[0] == 0 && data[1] == 0)
    {
        if (data[2] == 1)
        {
            return true;
        }
        else if ((data[2] == 0) && (data[3] == 1))
        {
            return true;
        }
    }

    return false;
}

int H26xNaluParser::checkStartCode(const uint8_t* data, size_t length)
{
    if (length < 4)
    {
        return 0;
    }

    if (data[0] == 0 && data[1] == 0)
    {
        if (data[2] == 1)
        {
            return 3;
        }
        else if ((data[2] == 0) && (data[3] == 1))
        {
            return 4;
        }
    }

    return 0;
}


size_t H26xNaluParser::findStartCode(const uint8_t* data, size_t length, size_t start)
{
    for (size_t i = start; i < length - 4; ++ i)
    {
        if (data[i] == 0)
        {
            if (hasStartCode(&data[i], length - i))
            {
                return i;
            }
        }
    }
    return -1;
}

void H26xNaluParser::insertStartCode(std::string& data)
{
    data.insert(0, (const char*)s_startCode, START_CODE_LENGTH);
}


bool H26xNaluParser::parseH264Nalu(uint8_t* data, size_t length, H26xNalu& pkt)
{
	int prefix = checkStartCode(data, length);
	if (prefix <= 0)
	{
		return false;
	}

	pkt.prefix = prefix;
    pkt.data = data;
    pkt.length = length;
    pkt.type = (pkt.data[prefix] & 0x1F);

    pkt.isKeyFrame = (pkt.type == NALU_IFRAME);

    return true;
}

bool H26xNaluParser::parseH265Nalu(uint8_t* data, size_t length, H26xNalu& pkt)
{
	int prefix = checkStartCode(data, length);
	if (prefix <= 0)
	{
		return false;
	}

	pkt.prefix = prefix;
	pkt.data = data;
	pkt.length = length;
	pkt.type = ((pkt.data[prefix] >> 1) & 0x3F);

	pkt.isKeyFrame = (pkt.type == NAL_IDR_N_LP) || (pkt.type == NAL_IDR_W_RADL);

	return true;
}

size_t H26xNaluParser::hexToData(const std::string& hexStr, std::string& data)
{
    size_t length = 0;
    int c = 0;
    int value = 1;
    for (size_t i = 0; i < hexStr.size(); i ++)
    {
        c = toupper((unsigned char)hexStr[i]);
        if (c >= '0' && c <= '9')
            c = c - '0';
        else if (c >= 'A' && c <= 'F')
            c = c - 'A' + 10;
        else
            break;
        value = (value << 4) | c;
        if (value & 0x100)
        {
            data.append(1, value);

            length ++;
            value = 1;
        }
    }
    return length;
}




} /* namespace av */
